package training.collection;

import java.util.Collection;
import java.util.Iterator;

public class CollectionImpl<Element> implements Collection<Element> {

	private Object[] elements; 



	public CollectionImpl() {
		super();

		elements = new Object[0];
	}

	@Override
	public boolean add(Element element) {
		Object[] newElements = new Object[elements.length + 1];
		for (int i = 0; i < elements.length; i++){
			newElements[i] = elements[i];
		}
		newElements[newElements.length - 1] = element;
		elements = newElements;
		return true;
	}

	@Override
	public boolean addAll(Collection<? extends Element> collection) {
		boolean ret = false;
		if (collection.size() > 0){
			Object[] newElements= new Object[elements.length+collection.size()];
			System.arraycopy(elements, 0, newElements, 0, elements.length);
			System.arraycopy(collection.toArray(), 0, newElements, elements.length, collection.size());
			ret = true;
			elements = newElements;
		}
		return ret;
	}

	@Override
	public void clear() {
		this.elements = new Object[0];
	}

	@Override
	public boolean contains(Object element) {
		boolean ret = false;
		for (Object o : elements){
			if(equals(element, o)){
				ret = true;
				break;
			}
		}
		return ret;
	}

	private boolean equals(Object el1, Object el2){
		boolean ret = false;
		if (el1 == null){
			ret = (el2 == null);
		}else{
			ret = el1.equals(el2);
		}
		return ret;
	}

	@Override
	public boolean containsAll(Collection<?> collection) {
		if (collection == null){
			throw new NullPointerException("null collection");
		}
		boolean ret = true;
		Object[] collectionArray = collection.toArray();

		for (int i = 0; i< collectionArray.length; i++){
			if (!contains(collectionArray[i])){
				ret = false;
				break;
			}
		}

		return ret;
	}

	@Override
	public boolean isEmpty() {
		return size() == 0;
	}

	@Override
	public Iterator<Element> iterator() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean remove(Object arg0) {
		boolean ret = false;
		if (elements.length > 0 && contains(arg0)){
			Object[] newElements = new Object[elements.length-1];
			int removeIndex = 0;
			for (int i = 0; i < elements.length; i++){
				if (equals(elements[i], arg0)){
					removeIndex = i;
					break;
				}
			}
			for (int i = 0, j = 0; i < newElements.length; i++, j++){
				if (removeIndex == i){
					j++;					
				}
				newElements[i] = elements[j];
			}
			elements = newElements;
			System.out.println(newElements.toString());
			ret = true;
		}

		return ret;
	}

	@Override
	public boolean removeAll(Collection<?> collection) {
		if (collection == null){
			throw new NullPointerException("null collection");
		}
		boolean ret = false;
		Object[] collectionArray = collection.toArray();

		for (int i = 0; i < collectionArray.length; i++){

			boolean removed = false;
			while(removed = remove(collectionArray[i])){
				if (ret == false){
					ret = (removed == true);
				}
			}
		}

		return ret;
	}

	@Override
	public boolean retainAll(Collection<?> collection) {
		if (collection == null){
			throw new NullPointerException("null collection");
		}
		boolean ret = false;
		
		for (int i = 0; i < elements.length; i++) {
			if (!collection.contains(elements[i])){
				remove(elements[i]);
				ret = true;
			}
		}
		
		return ret;
	}

	@Override
	public int size() {
		return elements.length;
	}

	@Override
	public Object[] toArray() {
		Object[] ret = new Object[elements.length];

		for (int i = 0; i < elements.length; i++){
			ret[i] = elements[i];
		}

		return ret;
	}

	@Override
	public <T> T[] toArray(T[] arg0) {
		// TODO Auto-generated method stub
		return null;
	}

}
